<template>
  <transition name="vui-message-fade">
    <div
      v-show="visible"
      :id="id"
      :class="['vui-message', type && !iconClass ? `vui-message--${type}` : '', showClose ? 'is-closable' : '', customClass]"
      role="alert"
      :style="customStyle"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
    >
      <!-- <i v-if="type || iconClass" :class="[typeClass, iconClass]"></i> -->
      <div class="flex justify-between message-header">
        <div>提示</div>
        <div v-if="showClose" class="b-icon-close" @click.stop="close">
          <svg
            class="icon"
            height="10"
            p-id="17246"
            t="1657612108365"
            version="1.1"
            viewBox="0 0 1024 1024"
            width="10"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M576 512l277.333333 277.333333-64 64-277.333333-277.333333L234.666667 853.333333 170.666667 789.333333l277.333333-277.333333L170.666667 234.666667 234.666667 170.666667l277.333333 277.333333L789.333333 170.666667 853.333333 234.666667 576 512z"
              fill="#444444"
              p-id="17247"
            />
          </svg>
        </div>
      </div>
      <div class="py-2">
        <slot>
          <p v-if="!useHTML" class="vui-message__content">
            {{ message }}
          </p>
          <div v-else class="vui-message__content" v-html="message"></div>
        </slot>
      </div>
    </div>
  </transition>
</template>
<script>
  import { EVENT_CODE } from './utils/aria'
  import { on, off } from './utils/dom'

  const TypeMap = {
    info: 'info-circle-fill',
    success: 'check-circle-fill',
    warning: 'warning-circle-fill',
    error: 'close-circle-fill',
  }

  export default {
    name: 'BMessage',
    props: {
      customClass: { type: String, default: '' },
      useHTML: { type: Boolean, default: false },
      duration: { type: Number, default: 3 },
      iconClass: { type: String, default: '' },
      id: { type: String, default: '' },
      message: {
        type: [String, Object],
        default: '',
      },
      onClose: {
        type: Function,
        required: true,
      },
      showClose: { type: Boolean, default: false },
      type: { type: String, default: 'info' },
      offset: { type: Number, default: 20 },
      zIndex: { type: Number, default: 0 },
    },
    data() {
      return {
        visible: false,
        closed: false,
      }
    },
    computed: {
      typeClass() {
        const type = this.type
        return type && TypeMap[type] ? `vui-message__icon b-iconfont b-icon-${TypeMap[type]} is-${type}` : ''
      },
      customStyle() {
        return {
          top: `${this.offset}px`,
          zIndex: this.zIndex,
        }
      },
    },
    watch: {
      closed(newVal) {
        if (newVal) {
          this.visible = false
          on(this.$el, 'transitionend', this.destroyElement)
        }
      },
    },
    mounted() {
      this.startTimer()
      this.visible = true
      on(document, 'keydown', this.keydown)
    },
    beforeUnmount() {
      off(document, 'keydown', this.keydown)
    },
    methods: {
      destroyElement() {
        this.visible = false
        off(this.$el, 'transitionend', this.destroyElement)
        this.onClose()
      },
      // start counting down to destroy message instance
      startTimer() {
        if (this.duration > 0) {
          this.timer = setTimeout(() => {
            if (!this.closed) {
              this.close()
            }
          }, this.duration * 1000)
        }
      },
      // clear timer
      clearTimer() {
        clearTimeout(this.timer)
        this.timer = null
      },
      // Event handlers
      close() {
        this.closed = true
        this.timer = null
      },
      keydown({ code }) {
        if (code === EVENT_CODE.esc) {
          // press esc to close the message
          if (!this.closed) {
            this.close()
          }
        } else {
          this.startTimer() // resume timer
        }
      },
    },
  }
</script>
